/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.factory.server.algorithms;

import com.factory.server.analyser.Analyser;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

/**
 *
 * @author milos
 */
public class Graph {
    
    static final Logger LOG = Logger.getLogger(Analyser.class.getName());
    List<Node> nodes;
    Integer numBerOfNodes;
    
    public Graph(Integer numBerOfNodes) {
        this.numBerOfNodes = numBerOfNodes;
        this.nodes = new ArrayList<Node>();
        for (int i = 0; i < numBerOfNodes; i++) {
            this.nodes.add(new Node(i));
        }
        LOG.info(nodes.toString());
    }
    
    public List<Node> getNodes() {
        return nodes;
    }
    
    public void setNodes(List<Node> nodes) {
        this.nodes = nodes;
    }
    
    public void addEdge(Integer src, Integer target) {
        nodes.get(src).addSucc(nodes.get(target));
        nodes.get(target).addPred(nodes.get(src));
    }
    
    public Graph inverse() {
        List<Node> invertedNodes = new ArrayList<Node>();
        for (int i = 0; i < nodes.size(); i++) {
            Node invertedNode = new Node(i);
            invertedNode.setSuccessors(nodes.get(i).getPrededecors());
            invertedNode.setPrededecors(nodes.get(i).getSuccessors());
            invertedNodes.add(i, invertedNode);
        }
        Graph invertedGraph = new Graph(numBerOfNodes);
        invertedGraph.setNodes(invertedNodes);
        return invertedGraph;
    }
    
    class Node {
        
        Integer identifier;
        Set<Node> prededecors;
        Set<Node> successors;
        
        public Node(Integer identifier) {
            this.identifier = identifier;
            prededecors = new HashSet<Node>();
            successors = new HashSet<Node>();
        }
        
        public void addPred(Node pred) {
            prededecors.add(pred);
        }
        
        public void addSucc(Node succ) {
            successors.add(succ);
        }
        
        public Set<Node> getPrededecors() {
            return prededecors;
        }
        
        public void setPrededecors(Set<Node> prededecors) {
            this.prededecors = prededecors;
        }
        
        public Set<Node> getSuccessors() {
            return successors;
        }
        
        public void setSuccessors(Set<Node> successors) {
            this.successors = successors;
        }
    }
}
